﻿using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Project_6
{
    /// <summary>
    /// 使用CurrentQueue实现异步任务队列
    /// </summary>
    public class Unit_6_03
    {
        public static void Go()
        {
            RunProgram().Wait();
        }

        static async Task RunProgram()
        {
            var taskQueue = new ConcurrentQueue<CustomTask>();
            var cts = new CancellationTokenSource();

            var taskSource = Task.Run(() => TaskProducer(taskQueue));

            Task[] processors = new Task[4];
            for (int i = 1; i <= 4; i++)
            {
                string processorId = i.ToString();
                processors[i - 1] = Task.Run(() => TaskProcessor(taskQueue, $"Processor(加工机) {processorId} ", cts.Token));
            }
            await taskSource;
            cts.CancelAfter(TimeSpan.FromSeconds(2));
            await Task.WhenAll(processors);
        }

        /// <summary>
        /// 任务生产者
        /// </summary>
        static async Task TaskProducer(ConcurrentQueue<CustomTask> queue)
        {
            for (int i = 1; i <= 20; i++)
            {
                await Task.Delay(50);
                var workItem = new CustomTask { Id = i };
                queue.Enqueue(workItem);
                Console.WriteLine($"Task {workItem.Id} has been posted，任务已发送！ ");
            }
        }

        /// <summary>
        /// 任务消费者，加工处理任务
        /// </summary>
        static async Task TaskProcessor(ConcurrentQueue<CustomTask> queue, string name, CancellationToken token)
        {
            CustomTask workItem;
            bool dequeueSuccesful = false;
            await GetRandomDelay();
            do
            {
                dequeueSuccesful = queue.TryDequeue(out workItem);
                if (dequeueSuccesful)
                {
                    Console.WriteLine($"Task {workItem!.Id} has been processed by {name}，任务已处理！");
                }
                await GetRandomDelay();
            }
            while (!token.IsCancellationRequested);
        }

        /// <summary>
        /// 随机等待一段时间
        /// </summary>
        static Task GetRandomDelay()
        {
            int delay = new Random(DateTime.Now.Millisecond).Next(1, 500);
            return Task.Delay(delay);
        }

        class CustomTask
        {
            public int Id { get; set; }
        }
    }
}
